package com.simen.loadapk;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.simen.hellobytes.DirUtil;
import com.simen.hellobytes.IOUtil;
import com.simen.hellobytes.exception.CreateDirectoryException;
import com.simen.invoker.Invoker;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;

import dalvik.system.DexClassLoader;

public class MainActivity extends Activity {

    private static final String TAG = "MainActivity";

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    public File sample_dex = new File(Environment.getExternalStorageDirectory(),
            "sample_dex_apkload.dex");

    public File sample_apk = new File(Environment.getExternalStorageDirectory(),
            "sample_apkload.apk");


    Button sampleDown;
    Button sampleLoad;
    Button sampleDexDown;
    Button sampleDexLoad;
    Button apkChooser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.sample_down:
                getApkOrDex("apk-release.apk", sample_apk);
                break;
            case R.id.sample_load:
                loadSampleApk();
                break;
            case R.id.sample_dex_down:
                getApkOrDex("apk-classes.dex", sample_dex);
                break;
            case R.id.sample_dex_load:
                loadSampleDex();
                break;
            case R.id.apk_chooser:
                break;
        }
    }

    private void loadSampleDex() {
        final File optimizedDexOutputDir;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            optimizedDexOutputDir = getCodeCacheDir();
        } else {
            optimizedDexOutputDir = new File(getCacheDir() , "optimizedDex");

            try {
                DirUtil.createDir(optimizedDexOutputDir.getAbsolutePath());
            } catch (CreateDirectoryException e) {
                Toast.makeText(this, "创建目录失败 "+optimizedDexOutputDir.getAbsolutePath(), Toast.LENGTH_SHORT).show();
                return;
            }
        }

        Log.d(TAG, "loadSampleDex: Dir "+optimizedDexOutputDir.getAbsolutePath());

        DexClassLoader cl = new DexClassLoader(sample_dex.getAbsolutePath(),
                optimizedDexOutputDir.getAbsolutePath(),
                null,
                getClassLoader());

        try {
            Class libProviderClazz = cl.loadClass("com.simen.apk.ApkClass");

            String name = (String) Invoker.invokeMethod(libProviderClazz,
                    "getName",
                    null);

            Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
            return;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        Toast.makeText(this, "加载类失败", Toast.LENGTH_SHORT).show();
    }

    private void loadSampleApk() {
        final File optimizedDexOutputDir;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            optimizedDexOutputDir = getCodeCacheDir();
        } else {
            optimizedDexOutputDir = new File(getCacheDir() , "optimizedApk");

            try {
                DirUtil.createDir(optimizedDexOutputDir.getAbsolutePath());
            } catch (CreateDirectoryException e) {
                Toast.makeText(this, "创建目录失败 "+optimizedDexOutputDir.getAbsolutePath(), Toast.LENGTH_SHORT).show();
                return;
            }
        }

        Log.d(TAG, "loadSampleDex: Dir "+optimizedDexOutputDir.getAbsolutePath());

        DexClassLoader cl = new DexClassLoader(sample_apk.getAbsolutePath(),
                optimizedDexOutputDir.getAbsolutePath(),
                null,
                getClassLoader());

        try {
            Class libProviderClazz = cl.loadClass("com.simen.apk.ApkClass");

            String name = (String) Invoker.invokeMethod(libProviderClazz, "getName",null);

            Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
            return;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        Toast.makeText(this, "加载类失败", Toast.LENGTH_SHORT).show();
    }

    private void getApkOrDex(String fileName, File sample_cache) {
        InputStream inputStream = null;
        try {
            inputStream = getAssets().open(fileName);

            IOUtil.copyStream(inputStream, sample_cache);

            Toast.makeText(this, fileName + " 文件加载完成", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtil.closeSilently(inputStream);
        }

    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

}
